﻿using System.Collections.Generic;
using UnityEngine;
using QFramework;
using System;

namespace HareGame
{
    [MonoSingletonPath("GameEntry/PoolManager")]
    public partial class PoolManager : MonoBehaviour_Ex, ISingleton
    {
        private Dictionary<string, SimpleObjectPool<PoolObj>> m_Pools;//所有的对象池

        private Dictionary<string, Transform> m_RecycleNodes;//回收对象时的节点

        /// <summary>
        /// 初始化
        /// </summary>
        public void OnSingletonInit()
        {
            if (m_ResLoader == null)
                m_ResLoader = ResLoader.Allocate();

            m_Pools = new Dictionary<string, SimpleObjectPool<PoolObj>>();
            m_RecycleNodes = new Dictionary<string, Transform>();
            foreach (var v in m_PoolDatas)
            {
                CreateNewPool(v.PoolName, v.DefauleCount);
            }
        }

        /// <summary>
        /// 创建对象池
        /// </summary>
        /// <param name="poolName">对象池名字</param>
        /// <param name="DefauleCount">预加载对象数量</param>
        SimpleObjectPool<PoolObj> CreateNewPool(string poolName, int DefauleCount = 0)
        {
            GameObject obj = m_ResLoader.LoadSync<GameObject>(poolName);
            SimpleObjectPool<PoolObj> pool = new SimpleObjectPool<PoolObj>(() =>
            {
                return obj.Instantiate().GetComponent<PoolObj>();
            });
            m_Pools.Add(poolName, pool);

            //创建回收节点
            GameObject recycleNode = new GameObject();
            recycleNode.name = poolName;
            recycleNode.transform.parent = transform;
            m_RecycleNodes.Add(poolName, recycleNode.transform);

            //创建预加载对象
            if (DefauleCount > 0)
            {
                List<PoolObj> preloadObjs = new List<PoolObj>();
                for (int i = 0; i < DefauleCount; i++)
                {
                    PoolObj preload = pool.Allocate();
                    preload.transform.SetParent(recycleNode.transform);
                    preload.OnPreload();
                    preloadObjs.Add(preload);
                }
                foreach (var preload in preloadObjs)
                {
                    preload.transform.parent = recycleNode.transform;
                    pool.Recycle(preload);
                }
            }

            return pool;
        }

        /// <summary>
        /// 定义单例
        /// </summary>
        public static PoolManager Instance
        {
            get { return MonoSingletonProperty<PoolManager>.Instance; }
        }

        /// <summary>
        /// 创建对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="PoolName">对象池</param>
        /// <param name="transParent">父节点</param>
        /// <returns></returns>
        public T CreateObj<T>(string PoolName, Transform transParent = null) where T : PoolObj
        {
            SimpleObjectPool<PoolObj> pool;
            if (m_Pools.ContainsKey(PoolName))
            {
                pool = m_Pools[PoolName];
            }
            else
            {
                pool = CreateNewPool(PoolName);
            }
            PoolObj obj = pool.Allocate();
            obj.gameObject.SetActive(true);
            if (transParent != null)
            {
                obj.transform.SetParent(transParent);
            }
            obj.name = obj.name.Replace("(Clone)", "");
            obj.transform.localScale = Vector3.one;
            obj.OnCreate(PoolName);
            return (T)obj;
        }

        /// <summary>
        /// 回收对象
        /// </summary>
        /// <param name="PoolName">对象池</param>
        /// <param name="obj">对象</param>
        public void Recycle(string PoolName, PoolObj obj)
        {
            SimpleObjectPool<PoolObj> pool;
            if (m_Pools.TryGetValue(PoolName, out pool))
            {
                obj.gameObject.SetActive(false);
                obj.transform.SetParent(m_RecycleNodes[PoolName]);
                pool.Recycle(obj);
                obj.OnRecycle();
            }
            else
            {
                LogKit.E("不存在对象池:" + PoolName);
            }
        }
    }

    /// <summary>
    /// 对象池数据
    /// </summary>
    public class PoolData
    {
        public string PoolName;//对象池名称
        public int DefauleCount;//初始数量

        public PoolData(string poolName, int defauleCount = 0)
        {
            PoolName = poolName;
            DefauleCount = defauleCount;
        }
    }
}
